﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Kopain
{

    /// <summary>This part of the class is filled with static methods for upgrading an untyped xml document that does not validate to latest, validating version.
    /// </summary>
    public partial class NoteRoot
    {

#region Public methods.

        /// <summary>This method creates the attribute used for versioning the Savefile and sets a version number.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="version"></param>
        internal static void CreateVersion(XmlDocument doc, int version)
        {
            GetCreateVersionElementAtttibute(doc).Value = version.ToString();
        }

        /// <summary>This method returns all Note elements as a list.  This list can then be iterated and updated.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        internal static List<XmlElement> GetNotes(XmlDocument doc)
        {
            return new List<XmlElement>(doc.SelectNodes("//" + _NoteElementName).Cast<XmlElement>());
        }

        /// <summary>This method returns the version of the SaveFile.  This method is a bit special in the case that it doesn't use the Note xml type but a generic XmlDocument.  This is because we want to be able to get the version number of savefiles that do
        /// not go through the xsd validation.  For instance to figure out what to do with it.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        internal static int GetVersion(XmlDocument doc)
        {
            return int.Parse(GetVersionElementAttribute(doc).Value);
        }

        /// <summary>This method returns true if the Xml document has a verson attribute.  After the versioning system of the Savefile is set in place this method will probably be totally obsolete.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        internal static bool HasVersion(XmlDocument doc)
        {
            return HasVersionElementAttribute(doc);
        }

        /// <summary>This method sets the OpenNoteId attribute the the parameter.  If the attribute does not exist it is created.
        /// </summary>
        /// <param name="guid"></param>
        internal static void CreateUpdateOpenNoteIdAttribute(XmlDocument doc, string guid)
        {
            XmlElement root = GetRootElement( doc );
            XmlAttribute openNoteIdAttibute = GetOpenNoteIdAttribute(root);
            if (null == openNoteIdAttibute)
            {
                openNoteIdAttibute = root.Attributes.Append(root.OwnerDocument.CreateAttribute(_NoteRootOpenNoteIdAttributeName));
            }
            openNoteIdAttibute.Value = guid;
        }

        /// <summary>This method sets the version of a untyped XmlDocument.  This is used for upgrading old Savefiles.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="newVersion"></param>
        internal static void SetVersion(XmlDocument doc, int newVersion)
        {
            GetCreateVersionElementAtttibute(doc).Value = newVersion.ToString();
        }

#endregion  //  Public methods.

#region Private methods.

        /// <summary>This method makes sure the xml document has a version number.  If there isn't any it is created.  If there is one it is left as is.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns>The newly created attribute.</returns>
        private static XmlAttribute GetCreateVersionElementAtttibute(XmlDocument doc)
        {
            if (HasVersionElementAttribute(doc))
            {
                return GetVersionElementAttribute(doc);
            }
            else
            {
                return GetRootElement(doc).Attributes.Append(doc.CreateAttribute(_NoteRootVersionAttributeName));
            }
        }

        /// <summary>This method returns the root element.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlElement GetRootElement(XmlDocument doc)
        {
            return (XmlElement)doc.SelectSingleNode(_NoteRootElementName);
        }

        /// <summary>This method returns the OpenNoteId attribute.  If none exists null is returned.
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private static XmlAttribute GetOpenNoteIdAttribute(XmlElement element)
        {
            if (element.HasAttribute(_NoteRootOpenNoteIdAttributeName))
            {
                return element.Attributes[_NoteRootOpenNoteIdAttributeName];
            }
            else
            {
                return null;
            }
        }

        /// <summary>This method returns the Version attribute of an untyped document.  Use this method for upgrading the SaveFile.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static XmlAttribute GetVersionElementAttribute(XmlDocument doc)
        {
            return GetRootElement(doc).Attributes[_NoteRootVersionAttributeName];
        }

        /// <summary>This method returns true if the xml document has a version element.
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private static bool HasVersionElementAttribute(XmlDocument doc)
        {
            if (null == GetRootElement(doc)) { return false; }
            else if (null == GetRootElement(doc).Attributes[_NoteRootVersionAttributeName]) { return false; }
            return true;
        }

#endregion  //  Private methods.

    }

    /// <summary>This part of the class is filled with static methods for upgrading an untyped xml document that does not validate to latest, validating version.
    /// </summary>
    public partial class NoteType
    {

#region Public methods.

        /// <summary>This method sets the CursorPositionAttribute to the value of the parameter.  If no such attribute exists it is created.
        /// </summary>
        /// <param name="element"></param>
        /// <param name="cursorPosition"></param>
        internal static void CreateUpdateCursorPositionAttribute(XmlElement element, int cursorPosition)
        {
            XmlAttribute cursorPositionAttibute = GetCursorPositionAttribute(element);
            if (null == cursorPositionAttibute)
            {
                cursorPositionAttibute = element.Attributes.Append(element.OwnerDocument.CreateAttribute(_NoteCursorpositionAttributeName));
            }
            cursorPositionAttibute.Value = cursorPosition.ToString();
        }

#endregion  //  Public methods.

#region Private methods.

        /// <summary>This method returns the CursorPosition attribute.  If none exists null is returned.
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private static XmlAttribute GetCursorPositionAttribute(XmlElement element)
        {
            if (element.HasAttribute(_NoteCursorpositionAttributeName))
            {
                return element.Attributes[_NoteCursorpositionAttributeName];
            }
            else
            {
                return null;
            }
        }

#endregion  //  Private methods.

    }

}
